package com.skyolder.taskman.ast;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;

import com.skyolder.taskman.Container;
import com.skyolder.taskman.word.Token;
import com.skyolder.taskman.word.TokenType;

public class EXCUTE_Branch extends Branch {
	public EXCUTE_Branch(Container c) {
		super(c);
	}

	private String functionName=null;
	private ArrayList<String> functionParams=new ArrayList<String>();


	@Override
	public void build(Iterator<Token> it) throws GrammarError {
		Token token=it.next();
		if(token==null){
			throw new GrammarError(Token.NULL);
		}
		TokenType tp=token.getTp();
		if(tp!=TokenType.PARAM){
			throw new GrammarError(token);
		}
		functionName=token.getWord();
		if(functionName==null){
			throw new GrammarError(token);
		}
		while(it.hasNext()){
			Token token2=it.next();
			if(token2.getTp()!=TokenType.PARAM){
				throw new GrammarError(token2);
			}
			functionParams.add(token2.getWord());
		}
	}

	@Override
	public Object excute() throws RunError{
		if(functionName==null){
			throw new RunError(EXCUTE_Branch.class.getName());
		}
		Container container=this.getContainer();
		Object cllbck=container.getCallBack(functionName);
		if(cllbck==null){
			throw new RunError(functionName);
		}
		Class<?> clazz=cllbck.getClass();
		Method[] methods=clazz.getDeclaredMethods();
		Method method=null;
		for(Method m:methods){
			if("callback".equals(m.getName())){
				method=m;
				break;
			}
		}
		if(method==null){
			throw new RunError(functionName);
		}
		Class<?>[] classes=method.getParameterTypes();
		try {
			if(classes==null){
				return method.invoke(cllbck,(Object)null);
			}
			if(functionParams.size()<=0){
				return method.invoke(cllbck,(Object)null);
			}
			if(classes.length!=functionParams.size()){
				throw new RunError(functionName);
			}
			ArrayList<Object> objects=new ArrayList<Object>();
			for(int i=0;i<classes.length;++i){
				Class<?> class1=classes[i];
				String str=functionParams.get(i);
				if(class1.getName().equals("java.lang.String")){
					objects.add(str);
				}else{
					Method mm= class1.getMethod("valueOf",String.class);
					objects.add(mm.invoke(class1, new Object[]{str}));
				}
			}
			method.setAccessible(true);
			return method.invoke(cllbck,objects.toArray());
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
			throw new RunError(e.getMessage());
		}
		//return null;
	}
	public static void main(String[] args) {
		/*
		Class class1=EXCUTE_Branch.class;
		Method[] methods=class1.getMethods();
		for(Method m:methods){
			System.out.println(m.getName());
		}
		*/
		//String.valueOf("sss");
		Class<?> class2=Integer.class;
		try {
			Method mm= class2.getMethod("valueOf", String.class);
			System.out.println(mm.invoke(class2, new Object[]{"12345"}));
			
		} catch (NoSuchMethodException | SecurityException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//Object object=class2.cast("12345");
		System.out.println(class2.isPrimitive());
	}
}
